Phase 3: Trade journal + Claude behavioral-analysis agent#2
Merged
Conversation
Add the Python-owned trade journal and a Claude-powered coach that reads it, correlating each trade against the microstructure regime at entry. - journal.py: SQLite persistence for journal_entries in the same METRICS_DB; insert/list plus a list_enriched join that attaches the market regime (ofi, realized volatility, vwap) covering each entry's timestamp. - coach.py: behavioral-analysis agent with structured (Pydantic) output, an injectable Anthropic client, a configurable default model (via ANTHROPIC_MODEL), and a `python -m backtest.coach` CLI. Emits behavioral observations, not advice and not price predictions. - api.py: POST/GET /journal and POST /journal/analyze (503 without an API key). - data/generate_journal.py + sample_journal.csv: deterministic synthetic journal aligned to the sample tape's timestamps, encoding a few behavioral narratives. - Tests for journal, coach (mocked client), and the new endpoints; add the anthropic dependency; .env handling; README roadmap + design decisions. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DcbYTwtqmAgEkcTtJtsztt
1816x
pushed a commit
that referenced
this pull request
Jul 17, 2026
Follow-up to the merged Phase 3 (PR #2), hardening the trade journal and agent: - Input validation on POST/PATCH journal bodies (side long/short, positive size/price/timestamps, exited_at_ns >= entered_at_ns) -> 422 on bad input. - Full journal CRUD: GET/PATCH/DELETE /journal/{id} plus journal.get_entry/ update_entry/delete_entry. - Time-range filters (since_ns/until_ns) on GET /journal and /journal/analyze. - Agent robustness: coach.analyze raises AnalysisUnavailable when the model returns no structured output (refusal or empty parse); the endpoint maps it to 502 instead of a 500 on a null body. - scripts/verify_pipeline.sh: keyless end-to-end smoke (tape -> engine -> metrics.db -> journal -> regime join). Hermetic test_integration.py covers the HTTP flow in CI. - Document the nanosecond/JSON safe-integer caveat as a Phase 4 dashboard concern. - Tests for all of the above; README updated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DcbYTwtqmAgEkcTtJtsztt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements Phase 3 of the roadmap: a trade journal model stored alongside metrics, and a Claude-powered behavioral agent that analyzes trading patterns correlated with market microstructure regime.
Summary
Adds three new modules to enable traders to log their trades and receive behavioral feedback:
backtest.journal: SQLite persistence layer for trade entries. Entries are stored in the same database as metrics, enabling joins to the market regime (order-flow imbalance, realized volatility, VWAP) at the moment each trade was entered. Supports bulk CSV import for seeding.backtest.coach: Claude-powered behavioral analyzer. Reads the journal joined to regime data and produces structured observations about recurring emotional and cognitive biases—never trading advice or price predictions. Uses Pydantic models for type-safe API responses and supports dependency injection of the Anthropic client for testability.backtest.api: Extended with journal endpoints (POST /journal,GET /journal,POST /journal/analyze). The behavioral endpoint depends on an injected Anthropic client, returning 503 when no API key is configured.Key Changes
Journal schema:
journal_entriestable with autoincrement ID, timestamps, trade details (symbol, side, entry/exit prices, size, P&L), and optional notes/emotion fields. Created on-demand by the persistence layer.Regime enrichment:
list_enriched()performs a LEFT JOIN to the metrics table, selecting the finest (smallest) window that contains each entry time. Regime columns are always present (possiblyNULL) for stable downstream shape.Behavioral analysis:
coach.analyze()formats the journal with regime context and sends it to Claude with a system prompt that forbids trading advice. Returns structuredBehavioralAnalysiswith a summary, list of observations (pattern, bias, evidence, severity), and a disclaimer.CSV import:
journal.import_csv()bulk-loads entries from a CSV, coercing numeric fields (int/float) and treating empty cells asNULL.Synthetic sample data:
data/generate_journal.pycreates a deterministic 12-trade journal with embedded behavioral narratives (revenge trading, FOMO, oversizing after wins, hesitation in choppy tape) that the agent can analyze.API integration: Journal endpoints share the same database path (
METRICS_DB) as metrics. The/journal/analyzeendpoint depends onget_anthropic_client(), which readsANTHROPIC_API_KEYand returns 503 if missing.Notable Implementation Details
Testability: The
coach.analyze()function accepts an injected client, allowing unit tests to use a fake without network access or a real API key.Graceful degradation:
list_enriched()returns plain entries (no regime columns) if the metrics table doesn't exist, and returns[]if the database doesn't exist yet—normal states for a new journal.Regime selection logic: The SQL subquery orders by window size (ascending) then bucket start (descending) to prefer the finest window and break ties by recency.
Environment configuration: Supports
ANTHROPIC_API_KEY,ANTHROPIC_MODEL(defaults to claude-opus-4-8), andMETRICS_DB(defaults to metrics.db).Comprehensive tests: Unit tests for journal persistence, CSV import, regime joins, and coach analysis (with fake client). Integration tests in
test_api.pyverify the full HTTP flow.